home *** CD-ROM | disk | FTP | other *** search
/ Macwelt 1 / Macwelt DVD 1.toast / Web-Publishing / HTML-Editoren / Alpha ƒ / Tcl / Modes / schemeMode.tcl < prev    next >
Encoding:
Text File  |  2000-12-07  |  22.5 KB  |  681 lines

  1. ## -*-Tcl-*-  (nowrap)
  2.  # ==========================================================================
  3.  #  Lisp Mode - an extension package for Alpha
  4.  # 
  5.  #  FILE: "schemeMode.tcl"
  6.  #                                    created: 07/03/96 {02:19:49 pm} 
  7.  #                                last update: 12/07/00 {03:46:32 pm} 
  8.  #  Description: 
  9.  #  
  10.  #  A mode for the shareware program Alpha, for Scheme files.
  11.  # 
  12.  #  Original by Oleg Kiselyov (oleg@ponder.csci.unt.edu) 
  13.  #  
  14.  #  Updated by Craig Barton Upright
  15.  #  
  16.  #  E-mail: <cupright@princeton.edu>
  17.  #    mail: Princeton University,  Department of Sociology
  18.  #          Princeton, New Jersey  08544
  19.  #     www: <http://www.princeton.edu/~cupright>
  20.  #     
  21.  #  Craig will maintain this until somebody else steps forward.
  22.  #  
  23.  # -------------------------------------------------------------------
  24.  #  
  25.  # Copyright (c) 1996-2000  Oleg Kiselyov, Craig Barton Upright
  26.  # 
  27.  # This program is free software; you can redistribute it and/or modify
  28.  # it under the terms of the GNU General Public License as published by
  29.  # the Free Software Foundation; either version 2 of the License, or
  30.  # (at your option) any later version.
  31.  # 
  32.  # This program is distributed in the hope that it will be useful,
  33.  # but WITHOUT ANY WARRANTY; without even the implied warranty of
  34.  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  35.  # GNU General Public License for more details.
  36.  # 
  37.  # You should have received a copy of the GNU General Public License
  38.  # along with this program; if not, write to the Free Software
  39.  # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  40.  # 
  41.  # ==========================================================================
  42.  ##
  43.  
  44. # ===========================================================================
  45. #
  46. # ◊◊◊◊ Initialization of Scm mode ◊◊◊◊ #
  47.  
  48. alpha::mode Scm 2.0 schemeMode.tcl {*.scm} {
  49.     lispMenu electricReturn electricTab electricBraces 
  50. } {
  51.     # We require 7.4b21 for prefs handling.
  52.     alpha::package require AlphaTcl 7.4b21
  53. } uninstall {
  54.     catch {file delete [file join $HOME Tcl Modes schemeMode.tcl]}
  55.     catch {file delete [file join $HOME Tcl Completions ScmCompletions.tcl]}
  56. } help {
  57.     The Scheme dialect of Lisp was created in 1975 by Guy Steele and Gerry
  58.     Sussman to explore ideas in programming-language semantics.  They
  59.     showed that a powerful language can be made "not by piling feature on
  60.     top of feature, but by removing the weaknesses and restrictions that
  61.     make additional features appear necessary".  Scheme pioneered lexical
  62.     scope in Lisp, first-class continuations, and tail recursion, and more
  63.     recently added an advanced macro system.  It's the best-known Lisp
  64.     dialect after Common Lisp (which it influenced).  It is IEEE
  65.     standardized and widely used in universities and in electronic CAD
  66.     systems.
  67.     
  68.                                                -- <http://www.lisp.org>
  69.     
  70.     Alpha's Scheme mode includes a user-expandable dictionary of keywords,
  71.     a full set of electric completions, and a sophisticated indentation
  72.     procedure.  Normal features include Electric Return, Tab, and Braces.
  73.     Scm mode also uses the Lisp menu.
  74.     
  75.     Click on this "Scheme Example.scm" link for an example syntax file.
  76.  
  77.     For more information about the Lisp menu, see "Lisp Help".
  78. } maintainer {
  79.     "Craig Barton Upright" <cupright@princeton.edu> 
  80.     <http://www.princeton.edu/~cupright/>
  81. }
  82.  
  83. proc schemeMode.tcl {} {}
  84.  
  85. namespace eval Scm {}
  86.  
  87. # ===========================================================================
  88. #
  89. # ◊◊◊◊ Setting Scm mode variables ◊◊◊◊ #
  90. #
  91.  
  92. #=============================================================================
  93. #
  94. # Standard preferences recognized by various Alpha procs
  95. #
  96.  
  97. newPref var  fillColumn        {75}            Scm
  98. newPref var  indentationAmount {4}             Scm
  99. newPref var  leftFillColumn    {0}             Scm
  100. newPref var  prefixString      {;; }           Scm
  101. newPref var  wordBreak         {[\w\-]+}       Scm
  102. newPref var  wordBreakPreface  {([^\w\-])}     Scm
  103. newPref flag wordWrap          {0}             Scm
  104.  
  105. # newPref v wordBreakPreface {[\(\) \t\r\n]} Scm
  106.  
  107. #=============================================================================
  108. #
  109. # Flag preferences
  110. #
  111.  
  112. # Indent all continued commands, indicated by unmatched parantheses, by the
  113. # full indentation amount rather than half.
  114. newPref flag fullIndent        {1}             Scm
  115.  
  116. newPref flag autoMark          {0}             Scm
  117.  
  118. #=============================================================================
  119. #
  120. # Variable preferences
  121.  
  122. # Enter additional arguments to be colorized.
  123. newPref var addArguments      {}              Scm    {Scm::colorizeScm}
  124.  
  125. # Enter additional Scm commands to be colorized.  
  126. newPref var addCommands       {}              Scm    {Scm::colorizeScm}
  127.  
  128. # Command double-clicking on a Lisp keyword will send it to this url
  129. # for a help reference page.
  130. newPref url schemeHelp {http://www.harlequin.com:8000/xanalys_int/query.html?qt=} Scm
  131.  
  132. # ===========================================================================
  133. # Color preferences
  134. #
  135.  
  136. newPref color argumentColor     {magenta}       Scm    {Scm::colorizeScm}
  137. newPref color commandColor      {blue}          Scm    {Scm::colorizeScm}
  138. newPref color commentColor      {red}           Scm    {stringColorProc}
  139. newPref color stringColor       {green}         Scm    {stringColorProc}
  140. newPref color symbolColor       {magenta}       Scm    {Scm::colorizeScm}
  141.  
  142. regModeKeywords -e {;}                      \
  143.       -c $ScmmodeVars(commentColor)        \
  144.       -s $ScmmodeVars(stringColor) Scm {}
  145.  
  146. # ==========================================================================
  147. # Comment Character variables for Comment Line / Paragraph / Box menu items.
  148.  
  149. set Scm::commentCharacters(General)    ";; "
  150. set Scm::commentCharacters(Paragraph)  [list ";; " " ;;" " ; "]
  151. set Scm::commentCharacters(Box)        [list ";" 2 ";" 2 ";" 3]
  152.  
  153.  
  154. set ScmCommentRegexp    {;.*$}
  155. set ScmPreRegexp        {^\#[\t ]*[a-z]*}
  156.  
  157. # ===========================================================================
  158. #
  159. # ◊◊◊◊ Keyword Dictionaries ◊◊◊◊ #
  160. #
  161.  
  162. # Making sure that ScmUserCommands and ScmUserArguments exist.
  163. # These will be over-ridden if they are loaded from a ${mode}Prefs.tcl file.
  164. #
  165.  
  166. set ScmUserCommands    ""
  167. set ScmUserArguments   ""
  168.  
  169. set ScmCommands {
  170.     abs and append apply assoc assq assv begin caar cadr
  171.     call-with-current-continuation car case cdar cddr cdr cond cons declare
  172.     define define-macro delay do else exact->inexact for-each if
  173.     inexact->exact lambda length let let* letrec list list-refmake-vector
  174.     map member memq memv number->string or peek-char read-char reverse set! 
  175.     set-car!  set-cdr!  string string->number string-append string-length
  176.     string-ref string-set!  substring vector vector-length vector-ref
  177.     vector-set!
  178. }
  179.  
  180. set ScmArguments {
  181.     #f #t 
  182.     char?  eof-object?  eq?  equal?  eqv?  even?  list?  negative?  not
  183.     null?  odd?  pair?  positive?  procedure?  string=?  zero?
  184.     
  185. }
  186.  
  187.  
  188. # ===========================================================================
  189. # Colorize Scm.
  190. # Used to update preferences, and could be called in a <mode>Prefs.tcl file
  191.  
  192. proc Scm::colorizeScm {{pref ""}} {
  193.     
  194.     global ScmmodeVars ScmCommands ScmArguments ScmUserCommands ScmUserArguments
  195.     
  196.     global ScmCommandList Scmcmds
  197.     
  198.     # First setting aside only the commands, for Scm::Completion::Command.
  199.     set ScmCommandList [concat \
  200.       $ScmCommands $ScmmodeVars(addCommands) $ScmUserCommands \
  201.       ]
  202.     
  203.     # Then, create the list of all keywords for completions.
  204.     set Scmcmds [lsort [lunique [concat \
  205.       $ScmCommandList $ScmArguments \
  206.       $ScmmodeVars(addArguments) $ScmUserArguments \
  207.       ]]]
  208.     # Commmands
  209.     regModeKeywords -a -k $ScmmodeVars(commandColor) \
  210.       Scm $ScmCommandList 
  211.     
  212.     # Arguments
  213.     set ScmArgumentColorList [concat \
  214.       $ScmArguments $ScmmodeVars(addArguments) $ScmUserArguments]
  215.     regModeKeywords -a \
  216.       -k $ScmmodeVars(argumentColor) Scm $ScmArgumentColorList
  217.     
  218.     # Symbols
  219.     regModeKeywords -a \
  220.       -k $ScmmodeVars(symbolColor) Scm {}              \
  221.       -i "+" -i "-" -i "*" -i "_" -i "\\" "/"          \
  222.       -I $ScmmodeVars(symbolColor)
  223.     if {$pref != ""} {refresh}
  224. }
  225.  
  226. # Call this now.
  227.  
  228. Scm::colorizeScm
  229.  
  230. # ===========================================================================
  231. #
  232. # ◊◊◊◊ Key Bindings, Electrics ◊◊◊◊ #
  233. # abbreviations:  <o> = option, <z> = control, <s> = shift, <c> = command
  234.  
  235. # Known bug: Key-bindings from other global menus might conflict with those
  236. # defined in the Lisp menu.  This will help ensure that this doesn't happen.
  237.  
  238. Bind 's'    <cs>    {Lisp::switchToLisp} Scm
  239. Bind 'p'    <cs>    {Lisp::processFile} Scm
  240. Bind 'p'    <csz>   {Lisp::processSelection} Scm
  241.  
  242. Bind 'n'    <sz>    {Lisp::nextCommand} Scm
  243. Bind 'p'    <sz>    {Lisp::prevCommand} Scm
  244. Bind 's'    <sz>    {Lisp::selectCommand} Scm
  245. Bind 'c'    <sz>    {Lisp::copyCommand} Scm
  246.  
  247. Bind 'i'    <cz>    {Lisp::reformatCommand} Scm
  248.  
  249. Bind '\r'   <z>     {typeText "\r" }  Scm
  250. Bind '\r'   <s>     {Lisp::continueCommand} Scm
  251. Bind '\)'           {Scm::electricRight "\)"} Scm
  252.  
  253. # For those that would rather use arrow keys to navigate.  Up and down
  254. # arrow keys will advance to next/prev command, right and left will also
  255. # set the cursor to the top of the window.
  256.  
  257. Bind    up  <sz>    {Lisp::prevCommand} Scm
  258. Bind  left  <sz>    {Lisp::prevCommand 0 1} Scm
  259. Bind  down  <sz>    {Lisp::nextCommand} Scm
  260. Bind right  <sz>    {Lisp::nextCommand 0 1} Scm
  261.  
  262. proc Scm::carriageReturn {} {
  263.     
  264.     if {[isSelection]} {
  265.     deleteSelection
  266.     } 
  267.     set pos1 [lineStart [getPos]]
  268.     set pos2 [getPos]
  269.     if {[regexp {^([\t ])*\)} [getText $pos1 $pos2]]} {
  270.     createTMark temp $pos2
  271.     Scm::indentLine
  272.     gotoTMark temp ; removeTMark temp
  273.     } 
  274.     insertText "\r"
  275.     bind::IndentLine
  276. }
  277.  
  278. proc Scm::electricRight {{char "\}"}} {
  279.     
  280.     set pos [getPos]
  281.     typeText $char
  282.     if {![regexp {[^ \t]} [getText [lineStart $pos] $pos]]} {
  283.     set pos [lineStart $pos]
  284.     createTMark temp [getPos]
  285.     Scm::indentLine
  286.     gotoTMark temp ; removeTMark temp
  287.     bind::CarriageReturn
  288.     } 
  289.     if {[catch {blink [matchIt $char [pos::math $pos - 1]]}]} {
  290.     beep ; message "No matching $char !!"
  291.     } 
  292. }
  293.  
  294. # ===========================================================================
  295. #
  296. # ◊◊◊◊ Indentation ◊◊◊◊ #
  297. # Indenting a line of a Scheme code
  298. #
  299. # The idea is simple: the indent of a new line is the same as the indent of
  300. # the previous non-empty non-comment-only line *plus* the paren balance of
  301. # that line times two.
  302. # That is, if the last code line was paren balanced, the next line would
  303. # have the same indent.  If the prev line opened an expression but didn't
  304. # close it, the new line would be indented further
  305. #
  306.  
  307. proc Scm::indentLine {{pos ""}} {
  308.     
  309.     if {[catch {Lisp::indentLine $pos}]} {
  310.     Scm::indentLineOld
  311.     }
  312. }
  313.  
  314. proc Scm::correctIndentation {pos {next ""}} {
  315.     
  316.     Lisp::correctIndentation $pos $next
  317. }
  318.  
  319. # This was the original procedure, with a little modification:
  320.  
  321. proc Scm::indentLineOld {} {
  322.  
  323.     global mode indent_amounts ScmmodeVars
  324.     
  325.     set continueIndent [expr {$ScmmodeVars(fullIndent)  + 1}]
  326.     
  327.     set beg [lineStart [getPos]]
  328.     set end [nextLineStart [getPos]]
  329.     
  330.     # Find last previous non-comment line and get its leading whitespace
  331.     set pos $beg
  332.     set lst [search -s -f 0 -r 1 -i 0 {^[ \t]*[^ ;\t\r\n]} [pos::math $pos - 1]]   
  333.     set line [getText [lindex $lst 0] [pos::math [nextLineStart [lindex $lst 0]] - 1]]
  334.     set lwhite [getText [lindex $lst 0] [pos::math [lindex $lst 1] - 1]]
  335.     
  336.     # Computing the balance of parentheses within the 'line':
  337.     # 
  338.     # This appears to be utterly elementary.  One has to keep in mind
  339.     # however that parentheses might appear in comments and/or quoted
  340.     # strings, in which case they shouldn't count.  Although it's easy to
  341.     # detect a Scheme comment by a semicolon, a semicolon can also appear
  342.     # within a quoted string.  Note that a double quote isn't that sure a
  343.     # sign of a quoted string: the double quote may be escaped.  And the
  344.     # backslash can be escaped in turn...  Thus we face a full-blown
  345.     # problem of parsing a string according to a context-free grammar.  We
  346.     # note however that a TCL interpretor does similar kind of parsing all
  347.     # the time.  So, we can piggy-back on it and have it decide what is the
  348.     # quoted string and when a semicolon really starts a comment.  To this
  349.     # end, we replace all non-essential characters from the 'line' with
  350.     # spaces, separate all parens with spaces (so each paren would register
  351.     # as a separate token with the TCL interpretor), replace a semicolon
  352.     # with an opening brace (which, if unescaped and unquoted, acts as some
  353.     # kind of "comment", that is, shields all symbols that follows).  After
  354.     # that, we get TCL interpretor to convert thus prepared 'line' into a
  355.     # list, and simply count the balance of '(' and ')' tokens.
  356.     # 
  357.     
  358.     regsub -all -nocase {[^ ();\"\\]} $line { } line1
  359.     regsub -all {;} $line1 "\{" line
  360.     regsub -all {[()]} $line { \0 } line1
  361.     set line_list [eval "list $line1 \}"]
  362.     #alertnote ">$line_list<"
  363.     set balance 0
  364.     foreach i $line_list { 
  365.     switch $i {
  366.         ( {incr balance $continueIndent} 
  367.         ) {incr balance -continueIndent}
  368.     }
  369.     }
  370.     #alertnote "balance $balance, lwhite [string length $lwhite]"
  371.     if {$balance < 0} {
  372.       set lwhite [string range $lwhite 0 [expr [string length $lwhite] + 2 * $balance - 1]]
  373.     } else {
  374.       append lwhite [string range "              " 1 [expr 2 * $balance]]
  375.     }
  376.     #alertnote "new lwhite [string length $lwhite]"
  377.     
  378.     set text [getText $beg [nextLineStart $beg]]
  379.     regexp {^[ \t]*} $text white
  380.     set len [string length $white]
  381.     
  382.     if {$white != $lwhite} {
  383.       replaceText $beg [pos::math $beg + $len] $lwhite
  384.     }
  385.     goto [pos::math $beg + [string length $lwhite]]
  386.     return
  387.     
  388. }
  389.  
  390. # ===========================================================================
  391. # ◊◊◊◊ Command Double Click ◊◊◊◊ #
  392. #
  393. # Checks to see if the highlighted word appears in any keyword list, and if
  394. # so, sends the selected word to the www.Lisp.com help site.
  395. # Control-Command double click will insert syntax information in status bar.
  396. # Shift-Command double click will insert commented syntax information in window.
  397. # (The above is not yet implemented -- need to enter all of the syntax info.)
  398.  
  399. proc Scm::DblClick {from to shift option control} {
  400.     
  401.     global ScmmodeVars Scmcmds ScmSyntaxMessage
  402.         
  403.     select $from $to
  404.     set command [getSelect]
  405.     
  406.     set varDef "(def|make)+(\[-a-zA-Z0-9\]+(\[\t\' \]+$command)+\[\t\r\n\(\) \])"
  407.     
  408.     if {![catch {search -s -f 1 -r 1 -m 0 $varDef [minPos]} match]} {
  409.         # First check current file for a function, variable (etc)
  410.         # definition, and if found ...
  411.         placeBookmark
  412.         goto [lineStart [lindex $match 0]]
  413.         message "press <Ctl .> to return to original cursor position"
  414.         return
  415.         # Could next check any open windows, or files in the current
  416.         # window's folder ...  but not implemented.  For now, variables
  417.         # (etc) need to be defined in current file.
  418.     }
  419.     if {[lsearch -exact $Scmcmds $command] == -1} {
  420.         message "\"$command\" is not defined as a Scm system keyword."
  421.         return
  422.     }
  423.     # Any modifiers pressed?
  424.     if {$control} {
  425.         # CONTROL -- Just put syntax message in status bar window
  426.         if {[info exists ScmSyntaxMessage($command)]} {
  427.             message "$ScmSyntaxMessage($command)"
  428.         } else {
  429.             message "Sorry, no syntax information available for $command"
  430.         }
  431.     } elseif {$shift} {
  432.         # SHIFT --Just insert syntax message as commented text
  433.         if {[info exists ScmSyntaxMessage($command)]} {
  434.             endOfLine
  435.             insertText "\r"
  436.             insertText "$ScmSyntaxMessage($command)
  437.             comment::Line
  438.         } else {
  439.             message "Sorry, no syntax information available for $command"
  440.         }
  441.     } else {
  442.         # No modifiers -- Send command for on-line help.  This is the
  443.         # "default" behavior.
  444.         Scm::wwwCommandHelp $command
  445.     }
  446. }
  447.  
  448. # ===========================================================================
  449. # WWW Command Help
  450. # Send command to defined url, prompting for text if necessary.
  451.  
  452. proc Scm::wwwCommandHelp {{command ""}} {
  453.     
  454.     global ScmmodeVars
  455.     
  456.     if {$command == ""} {
  457.         set command [prompt "on-line help for ... " [getSelect]] 
  458.         # set command [statusPrompt "on-line help for ... " ] 
  459.     } 
  460.     message "\"$command\" sent to $ScmmodeVars(schemeHelp)"
  461.     icURL $ScmmodeVars(schemeHelp)$command
  462. }
  463.  
  464. # ===========================================================================
  465. #
  466. # ◊◊◊◊ Mark File and Parse Functions ◊◊◊◊ #
  467. #
  468.  
  469. # ===========================================================================
  470. #
  471. # Scm Mark File
  472.  
  473. proc Scm::MarkFile {} {
  474.     
  475.     message "Marking File …"
  476.     
  477.     set count 0
  478.     set pos [minPos]
  479.     set pat {^[ \t]*[\(][#a-zA-z]*(define|define-[a-zA-Z]+) +[\(]*([^\(\) \t\r\n]+)}
  480.     while {![catch {search -s -f 1 -r 1 -m 0 -i 1 $pat $pos} match]} {
  481.         regexp -nocase -- $pat [eval getText $match] allofit defunname name
  482.         set posBeg [lindex $match 0]
  483.         set posEnd [nextLineStart $posBeg]
  484.         if {[pos::math $posEnd > [maxPos]]} {set posEnd [maxPos]}
  485.         setNamedMark $name $posBeg $posBeg $posBeg
  486.         set pos $posEnd
  487.     }
  488.     message ""
  489. }
  490.  
  491. # This was the original proc.
  492.  
  493. # proc Scm::MarkFile {} {
  494. #     
  495. #     set pat1 {^[ \t]*[\(][#a-zA-z]*(define|define-[a-zA-Z]+) +[\(]*([^\(\) \t\r\n]+)}
  496. #     set end [maxPos]
  497. #     set pos [minPos]
  498. #     set l {}
  499. #     while {![catch {search -s -f 1 -r 1 -m 0 -i 1 $pat1 $pos} mtch]} {
  500. #       regexp -nocase -- $pat1 [eval getText $mtch] allofit defunname name
  501. #       set start [lindex $mtch 0]
  502. #       set end [nextLineStart $start]
  503. #       set pos $end
  504. #       set inds($name) [lineStart [pos::math $start - 1]]
  505. #     }
  506. #     
  507. #     if {[info exists inds]} {
  508. #       foreach f [lsort -ignore [array names inds]] {
  509. #           set next [nextLineStart $inds($f)]
  510. #           setNamedMark $f $inds($f) $next $next
  511. #       }
  512. #     }
  513. # }
  514.  
  515. # ===========================================================================
  516. #
  517. # Scm Parse Functions
  518. # This will return only the Scm command names.
  519.  
  520. proc Scm::parseFuncs {} {
  521.     
  522.     global sortFuncsMenu
  523.     
  524.     set pos [minPos]
  525.     set m {}
  526.     while {[set match [search -s -f 1 -r 1 -i 0 -n {^\((\w+)} $pos]] != ""} {
  527.         if {[regexp -- {(\w+)} [eval getText $match] "" word]} {
  528.             lappend m [list $word [lindex $match 0]]
  529.         }
  530.         set pos [lindex $match 1]
  531.     }
  532.     if {$sortFuncsMenu} {
  533.         regsub -all "\[\{\}\]" [lsort -ignore $m] "" m
  534.     } else {
  535.         regsub -all "\[\{\}\]" $m "" m
  536.     }   
  537.     return  $m
  538. }
  539.  
  540. # ===========================================================================
  541. #
  542. # ◊◊◊◊ Help ◊◊◊◊ #
  543.  
  544. proc Scm::addKeywords {{category} {keywords ""}} {
  545.     
  546.     Lisp::LispModeMenuItem 0 1
  547.     
  548.     global ScmmodeVars
  549.     
  550.     if {$keywords == ""} {
  551.         set keywords [prompt "Enter new Scm mode $category:" ""]
  552.     }
  553.     
  554.     # Check to see if the keyword is already defined.
  555.     foreach keyword $keywords {
  556.         set checkStatus [Scm::checkKeywords $keyword 1 0]
  557.         if {$checkStatus != 0} {
  558.             alertnote "Sorry, \"$keyword\" is already defined\
  559.               in the $checkStatus list."
  560.             message "Cancelled."
  561.             return -code return
  562.         } 
  563.     }
  564.     # Keywords are all new, so add them to the appropriate mode preference.
  565.     append ScmmodeVars(add$category) " $keywords"
  566.     set ScmmodeVars(add$category) [lsort $ScmmodeVars(add$category)]
  567.     synchroniseModeVar add$category $ScmmodeVars(add$category)
  568.     Scm::colorizeScm
  569.     message "\"$keywords\" added to $category preference."
  570. }
  571.  
  572. proc Scm::checkKeywords {{newKeywordList ""} {quietly 0} {noPrefs 0}} {
  573.     
  574.     Lisp::LispModeMenuItem 0 1
  575.     
  576.     global ScmmodeVars
  577.     
  578.     global ScmCommands ScmUserCommands ScmUserArguments
  579.     
  580.     set type 0
  581.     if {$newKeywordList == ""} {
  582.         set quietly 0
  583.         set newKeywordList [prompt "Enter Scm mode keywords to be checked:" ""]
  584.     }
  585.     # Check to see if the new keyword(s) is already defined.
  586.     foreach newKeyword $newKeywordList {
  587.         if {[lsearch -exact $ScmCommands $newKeyword] != "-1"} {
  588.             set type ScmCommands 
  589.         } elseif {[lsearch -exact $ScmUserCommands $newKeyword] != "-1"} {
  590.             set type ScmUserCommands
  591.         } elseif {[lsearch -exact $ScmUserArguments $newKeyword] != "-1"} {
  592.             set type ScmUserArguments
  593.         } elseif {!$noPrefs && \
  594.           [lsearch -exact $ScmmodeVars(addCommands) $newKeyword] != "-1"} {
  595.             set type ScmmodeVars(addCommands)
  596.         } elseif {!$noPrefs && \
  597.           [lsearch -exact $ScmmodeVars(addArguments) $newKeyword] != "-1"} {
  598.             set type ScmmodeVars(addArguments)
  599.         }
  600.         if {$quietly} {
  601.             # When this is called from other code, it should only contain
  602.             # one keyword to be checked, and we'll return it's type.
  603.             return "$type"
  604.         } elseif {!$quietly && $type == 0} {
  605.             alertnote "\"$newKeyword\" is not currently defined\
  606.               as a Scm mode keyword"
  607.         } elseif {$type != 0} {
  608.             # This will work for any other value for "quietly", such as "2"
  609.             alertnote "\"$newKeyword\" is currently defined as a keyword\
  610.               in the \"$type\" list."
  611.         } 
  612.         set type 0
  613.     }
  614. }
  615.  
  616. # ===========================================================================
  617. #
  618. # ◊◊◊◊ Navigation ◊◊◊◊ #
  619.  
  620. proc Scm::searchFunc {direction} {
  621.     
  622.     Lisp::LispModeMenuItem
  623.     
  624.     if {$direction} {
  625.         Lisp::nextCommand
  626.     } else {
  627.         Lisp::prevCommand
  628.     }
  629. }
  630.  
  631. # ===========================================================================
  632. # ◊◊◊◊ -------------------- ◊◊◊◊ #
  633. # ◊◊◊◊ version history ◊◊◊◊ #
  634. #  modified by  rev    reason
  635. #  -------- --- ------ -----------
  636. #  10/01/96 ok  1.0    Original Scheme mode.
  637. #  03/18/99 ??  - 1.3  Updates.
  638. #  11/30/00 cbu 1.4    Updated to use the lispMenu better, including
  639. #                      Added   Scm::colorizeScm 
  640. #                      Added   Scm::carriageReturn 
  641. #                      Added   Scm::electricRight 
  642. #                      Revised Scm::indentLine
  643. #                      Added   Scm::correctIndentation 
  644. #                      Revised Scm::MarkFile
  645. #                      Added   Scm::parseFuncs 
  646. #                      Added   Scm::checkKeywords 
  647. #                      Added   Scm::addKeywords 
  648. #                      Added   Scm::searchFunc 
  649. #  12/01/00 cbu 2.0    New url prefs handling requires 7.4b21
  650.  
  651. # ===========================================================================
  652. # .